feat: Canvas Workspace — infinite canvas design tool#1
Open
csacsi wants to merge 50 commits into
Open
Conversation
Design spec for the /canvas route — an infinite canvas workspace that evolves PinLaunch from a landing page generator into a full design tool. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
13-task implementation plan covering: types/state management, DB/API routes, canvas core with pan/zoom, shape/widget/image/document/artboard nodes, toolbar, sidebar, inspector, minimap, and integration tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…artboard iframe reload
- Add canvas-node CSS class to node wrappers and exclude from react-zoom-pan-pinch panning so nodes can be dragged independently - Use local dragOffset state for smooth visual drag without flooding the undo stack on every mousemove - Commit position to canvas state only on mouseUp via onMoveRef - Add e.preventDefault() to stop browser default drag behavior Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a node drag starts, set panningDisabled=true on the TransformWrapper so react-zoom-pan-pinch doesn't compete for mouse events. Re-enable on mouseUp. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Selected nodes now show a translucent green outline and fill on the wrapper div. Removed duplicate blue selection outlines from individual node components. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Drag on empty canvas area draws a translucent green selection rectangle. On mouseUp, all nodes intersecting the rectangle become selected. Panning is disabled during lasso. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge main into feature/canvas-workspace. Resolved page.tsx conflict (keep canvas redirect). Updated Sidebar to use new GeneratePanel interface (onPrepareBrief + preparing props). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Header component to canvas page with ProjectsDropdown - Selecting a project creates an artboard on the canvas - Default provider changed to 'claude' (Gemini removed from main) - Fetch provider from /api/settings on mount - Update Sidebar to use new GeneratePanel interface (onPrepareBrief) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sidebar now manages the complete brief flow with phases: - idle: shows PinBoard, GitHubPanel, PresetsPanel, GeneratePanel - preparing: shows CreativeDirectorTerminal (streams brief generation) - brief: shows BriefEditor (edit colors, typography, sections) - building: shows ClaudeTerminal (streams site generation) On build complete, artboard is created on the canvas. A "Back" button allows returning to idle from any phase. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Selected non-artboard nodes show 4 green corner handles (nw/ne/sw/se). Dragging a handle resizes the node visually during drag (local state), then commits the final size on mouseUp. Minimum size enforced at 30px. Artboards are excluded (viewport preset only). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Custom wheel handler replaces default scroll-to-zoom: - Two-finger trackpad scroll → pans the canvas (deltaX/deltaY) - Pinch gesture (ctrlKey + deltaY) → zooms toward cursor position - Library's built-in wheel zoom disabled to prevent conflicts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
During node resize: - Hold Shift to maintain the original aspect ratio - Hold Alt to resize symmetrically from the center - Both modifiers can be combined Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Lasso selection: - Nodes highlight interactively as the lasso rectangle moves over them - Nodes deselect when the lasso moves away from them - Escape cancels the lasso and clears selection Selection behavior: - Clicking already-selected node keeps multi-selection (for drag) - Shift+click toggles individual nodes in/out of selection - Escape clears all selection Multi-drag: - Dragging one of multiple selected nodes moves all of them - Each node moves by the same relative delta as the cursor Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When dragging one of multiple selected nodes, all other selected nodes now visually follow in real-time during the drag, not just on mouseUp. Uses externalDragOffset prop to communicate the drag delta from the source node to sibling selected nodes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resize handles are now 12px on screen regardless of zoom level. Selection outline thickness and offset also scale inversely with zoom so they remain visually consistent at any zoom level. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A click (mousedown+mouseup without drag) on empty canvas area now sends null to onLassoUpdate, clearing the selection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace top text toolbar with bottom-centered pill-shaped toolbar: - 5 icon buttons: Website, Image, Document, Wireframe, Prompt - Wireframe button opens submenu above pill (shapes + widgets grid) - Prompt (sparkles) button opens expandable input above pill - Enter/Generate sends prompt to sidebar brief flow - Website button opens sidebar generate panel - Inline SVG icons, tooltips on hover, click-outside to close - Sidebar now accepts externalPrompt prop for toolbar integration Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…oning Toolbar was inside the Canvas transform area, making it scroll with content. Now it's a sibling of Canvas in the container div, so absolute bottom-4 positions it at the viewport bottom. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Transforms PinLaunch from a landing page generator into a full design tool with an infinite canvas workspace at
/canvas.New files
src/app/canvas/page.tsx— Canvas pagesrc/components/canvas/— 11 components (Canvas, CanvasNode, CanvasToolbar, Sidebar, InspectorPanel, Minimap, ShapeNode, WidgetNode, ImageNode, DocumentNode, ArtboardNode)src/lib/canvas-types.ts+canvas-state.ts+ testssrc/app/api/canvas/+src/app/api/uploads/— API routesModified files
src/lib/db.ts— addedcanvas_statetablesrc/app/page.tsx— redirects to/canvassrc/components/Header.tsx— logo links to/canvasTest plan
npm run test— 68/68 passingnpm run build— clean🤖 Generated with Claude Code